package tech.horgee.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import tech.horgee.common.MyCode;
import tech.horgee.common.MyResult;
import tech.horgee.config.AppConfig;
import tech.horgee.dto.PwdDTO;
import tech.horgee.dto.UserExportDTO;
import tech.horgee.entity.User;
import tech.horgee.group.InsertGroup;
import tech.horgee.group.UpdateGroup;
import tech.horgee.service.UserService;
import tech.horgee.utils.ExcelUtils;
import tech.horgee.utils.FileUploadUtils;
import tech.horgee.utils.MimeTypeUtils;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import static tech.horgee.common.MyConstants.SUPER_ADMIN_ID;

/**
 * 用户信息接口
 *
 * @author haojun
 * @since 2022-06-12
 */
@Slf4j
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
    private final UserService service;

    /**
     * 分页查询列表
     *
     * @param index  当前页|1
     * @param size   页大小|10
     * @param entity 查询实体
     * @return 所有数据
     */
    @SaCheckPermission("user:query")
    @PostMapping("page/{index}/{size}")
    public MyResult selectAll(@RequestBody(required = false) User entity, @PathVariable Long index, @PathVariable Long size) {
        Page<User> page = new Page<>(index, size);
        return MyResult.of(service.page(page, Optional.ofNullable(entity).orElse(new User())));
    }

    /**
     * 不分页查询列表
     *
     * @param entity 实体对象
     * @return 查询结果
     */
    @SaCheckPermission("user:query")
    @PostMapping("list")
    public MyResult list(@RequestBody(required = false) User entity) {
        return MyResult.of(service.list(Optional.ofNullable(entity).orElse(new User())));
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @SaCheckPermission("user:query")
    @GetMapping("{id}")
    public MyResult getById(@PathVariable Long id) {
        if (Objects.equals(id, SUPER_ADMIN_ID)) {
            if (!Objects.equals(StpUtil.getLoginIdAsLong(), id)) {
                return MyCode.ACCESS_DENIED.toResult("无权查询");
            }
        }
        return MyResult.of(service.getById(id));
    }

    /**
     * 新增单条数据
     *
     * @param entity 实体对象
     * @return 新增结果
     */
    @SaCheckPermission("user:add")
    @PostMapping
    public MyResult save(@RequestBody @Validated(InsertGroup.class) User entity) {
        service.save(entity);
        return MyResult.success();
    }

    /**
     * 修改单条数据
     *
     * @param entity 实体对象
     * @return 修改结果
     */
    @SaCheckPermission("user:edit")
    @PutMapping
    public MyResult update(@RequestBody @Validated(UpdateGroup.class) User entity) {
        service.update(entity);
        return MyResult.success();
    }

    /**
     * 批量删除数据
     *
     * @param ids 主键集合
     * @return 操作结果
     */
    @SaCheckPermission("user:delete")
    @PostMapping("delete")
    public MyResult deleteByIds(@RequestBody Set<Long> ids) {
        service.deleteByIds(ids);
        return MyResult.success();
    }

    /**
     * 查询用户拥有的角色ID
     *
     * @param userId 用户ID
     */
    @GetMapping("roles/{userId}")
    public MyResult getRoles(@PathVariable Long userId) {
        return MyResult.of(service.selectRoleIdsByUserId(userId));
    }

    /**
     * 重置密码
     */
    @PostMapping("resetPwd")
    public MyResult resetPwd(@RequestBody User user) {
        service.resetPassword(user.getUserId());
        return MyResult.success();
    }

    /**
     * 修改密码
     */
    @PostMapping("changePwd")
    public MyResult changePwd(@RequestBody @Valid PwdDTO dto) {
        Long loginId = StpUtil.getLoginIdAsLong();
        service.changePwd(loginId, dto);
        return MyResult.success();
    }

    /**
     * 修改头像
     *
     * @param file 头像文件
     */
    @PostMapping("changeAvatar")
    public MyResult changeAvatar(@RequestParam("avatar") MultipartFile file) throws IOException {
        Long loginId = StpUtil.getLoginIdAsLong();
        if (file.isEmpty()) return MyCode.DATA_VERIFY_ERROR.toResult("图片上传失败");
        String path = FileUploadUtils.upload(AppConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
        service.changeAvatar(loginId, path);
        return MyResult.success();
    }

    /**
     * 导出excel
     *
     * @download
     */
    @PostMapping("export")
    public void export(HttpServletResponse response) {
        List<User> list = service.list(new User());
        ExcelUtils.export(response, "测试导出", list.stream().map(i -> {
            UserExportDTO dto = new UserExportDTO();
            BeanUtils.copyProperties(i, dto);
            return dto;
        }).toList(), UserExportDTO.class);
    }
}
